#include <windows.h>
#include "dwmapi.h"

BOOL IsWindows7()
{
	OSVERSIONINFO osver;
	osver.dwOSVersionInfoSize = sizeof(osver);
	if (GetVersionEx(&osver))
		return (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1)? TRUE: FALSE;
	else
		return FALSE;
}

// Create a device independent bitmap for use by the thumbnail.
HBITMAP CreateDIB(int nWidth, int nHeight)
{
	const int RINGWIDTH = 20;
	const int MAXRING = 3;
	const int MAXTABS = 20;

	HBITMAP hbm = NULL;
	HDC hdcMem = CreateCompatibleDC(NULL);
	LPBYTE   pbDS;

	if (hdcMem != NULL)
	{
		BITMAPINFO bmi;
		ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
		bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
		bmi.bmiHeader.biWidth = nWidth;
		bmi.bmiHeader.biHeight = -nHeight;  // Use a top-down DIB
		bmi.bmiHeader.biPlanes = 1;
		bmi.bmiHeader.biBitCount = 32;

		pbDS = NULL;
		hbm = CreateDIBSection(hdcMem, &bmi, DIB_RGB_COLORS, (LPVOID *)&pbDS, NULL, NULL);
		if (hbm != NULL)
		{
			int nGreen, nRed, nBlue;
			nRed = 0; nGreen= 185; nBlue = 242;

			// Fill in the pixels of the bitmap
			for (int y = 0; y < nHeight; y++)
			{
				for (int x = 0; x < nWidth; x++)
				{
					int edgeDistance = min(min(y, nHeight - y), min(x, nWidth - x));
					int ring = min((edgeDistance / RINGWIDTH) + 1, MAXRING);
					int nAlpha = ring * (255 / MAXRING);

					pbDS[0] = (BYTE)(nBlue * nAlpha / 255);
					pbDS[1] = (BYTE)(nGreen * nAlpha / 255);
					pbDS[2] = (BYTE)(nRed * nAlpha / 255);
					pbDS[3] = (BYTE)(nAlpha);

					pbDS += 4;
				}
			}
		}
		DeleteDC(hdcMem);
	}
	return hbm;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HBITMAP hbm;
	int nWidth, nHeight;

	switch(message)
	{
	case WM_CREATE:
		{
			// Set DWM window attributes to provide the iconic bitmap, and 
			// to always render the thumbnail using the iconic bitmap.
			BOOL fForceIconic = TRUE;
			BOOL fHasIconicBitmap = TRUE;

			DwmSetWindowAttribute(
				hwnd,
				DWMWA_FORCE_ICONIC_REPRESENTATION,
				&fForceIconic,
				sizeof(fForceIconic));

			DwmSetWindowAttribute(
				hwnd,
				DWMWA_HAS_ICONIC_BITMAP,
				&fHasIconicBitmap,
				sizeof(fHasIconicBitmap));
		}
		break;

	case WM_DWMSENDICONICTHUMBNAIL:
		{
			// This window is being asked to provide its iconic bitmap. This indicates
			// a thumbnail is being drawn.
			hbm = CreateDIB(HIWORD(lParam), LOWORD(lParam)); 
			if (hbm)
			{
				DwmSetIconicThumbnail(hwnd, hbm, 0);
				DeleteObject(hbm);
			}
		}
		break;

	case WM_DWMSENDICONICLIVEPREVIEWBITMAP:
		{
			// This window is being asked to provide a bitmap to show in live preview.
			// This indicates the thumbnail in the taskbar is being previewed.
			RECT rectWindow = {};
			if (GetClientRect(hwnd, &rectWindow))
			{
				nWidth = rectWindow.right - rectWindow.left;
				nHeight = rectWindow.bottom - rectWindow.top;
			}

			hbm = CreateDIB(nWidth, nHeight);
			if (hbm)
			{
				DwmSetIconicLivePreviewBitmap(hwnd, hbm, NULL, DWM_SIT_DISPLAYFRAME);
				DeleteObject(hbm);
			}
		}
		break;

	case WM_DESTROY:
		{
			PostQuitMessage(0);
			return (0);
		}
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	PCWSTR c_pszAppname = L"HelloThumbnail";

	if(!IsWindows7())
	{
		MessageBox(NULL, L"This program requires Windows 7", c_pszAppname, MB_ICONERROR);
		return 0;
	}

	WNDCLASS wndclass;

	wndclass.style = CS_HREDRAW|CS_VREDRAW;
	wndclass.lpfnWndProc = WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = DLGWINDOWEXTRA;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = c_pszAppname;

	if(RegisterClass(&wndclass))
	{
		HWND hwnd = CreateWindow(wndclass.lpszClassName,
			L"IconicThumbnail Example Window",
			WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			400,
			300,
			NULL,
			NULL,
			hInstance, 
			NULL);
		if(hwnd)
		{
			ShowWindow(hwnd, nShowCmd);

			MSG msg;
			while(GetMessage(&msg, NULL, 0, 0))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);

			}
			return msg.wParam;
		}
	}
	return 0;
}